package com.suxin.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @Classname SelectorServerTest
 * @Description [ TODO ]
 * @Author Tang
 * @Date 2020/12/28 11:31
 * @Created by ASUS
 */
public class SelectorServerTest {

    public static void main(String[] args) throws Exception {

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        serverSocketChannel.bind(new InetSocketAddress(9000));
        // 同步非阻塞
        serverSocketChannel.configureBlocking(false);

        Selector selector = Selector.open();
        // 注册一个 accept 事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        // 以注册的建
        selector.keys().forEach((item) -> {
            System.out.println("1.item--->" + item.interestOps());
        });

        int value = 0;
        // 阻塞方法，会等到有连接，
        while (true) {
            selector.select();
            // 获取事件key
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            // 已选择的建
            selector.keys().forEach((item) -> {
                System.out.println("2.item--->" + item.interestOps());
            });
            Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
            while (selectionKeyIterator.hasNext()) {
                SelectionKey selectionKey = selectionKeyIterator.next();
                // 判断是不是接收事件
                if (selectionKey.isAcceptable()) {
                    // 获取一个 client 的 SocketChannel
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    // 非阻塞
                    socketChannel.configureBlocking(false);
                    // client 注册到 selector
                    socketChannel.register(selector, SelectionKey.OP_READ);
                    // 是不是读事件
                } else if (selectionKey.isReadable()) {
                    System.out.println("--->" + selectionKey.isValid());
                    // 获取事件对应的 channel
                    SocketChannel channel = (SocketChannel) selectionKey.channel();
                    ByteBuffer allocate = ByteBuffer.allocate(1024);
                    int len;
                    while ((len = channel.read(allocate)) != 0 && len != -1) {
                        System.out.println("数据长度" + len);
                        allocate.limit(len - 1);
                        allocate.position(0);
                        System.out.println("thread id:"+Thread.currentThread().getId() + " 服务器收到的消息为：--->" + new String(allocate.array()));
                        allocate.clear();
                    }
                    selectionKey.cancel();
//                    selectionKey.interestOps(SelectionKey.OP_WRITE);
                } else if (selectionKey.isWritable()){
                    System.out.println("未知的事件：" + selectionKey);
                    System.out.println("是否可写：" + selectionKey.isWritable());
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer allocate = ByteBuffer.allocate(1024);
                    allocate.put("hello world!".getBytes());
                    allocate.flip();
                    // 写数据
                    socketChannel.write(allocate);
                    // 重置读事件
                    selectionKey.interestOps(0);
                    // 唤醒阻塞
                    selector.wakeup();
                }else {
                    System.out.println("任何事件都不感兴趣!");
                }
                // 从集合中移除
                selectionKeys.remove(selectionKey);
            }
        }
    }
}